package tech.waterism.topo.iterator;

import tech.waterism.topo.model.TopoNode;

import java.util.*;

/**
 * 拓扑迭代器
 * 
 * <p>封装拓扑遍历的复杂循环控制逻辑，支持回溯机制（用于联调）
 * 
 * <h3>核心特性：</h3>
 * <ul>
 *   <li>顺序遍历拓扑节点</li>
 *   <li>支持标记回溯点</li>
 *   <li>支持回溯到指定位置（联调完成后回到起点）</li>
 * </ul>
 * 
 * @author waterism
 * @since 1.0.0
 */
public class TopologyIterator implements Iterator<TopoNode> {
    
    /** 拓扑节点列表 */
    private final List<TopoNode> nodes;
    
    /** 当前索引位置 */
    private int currentIndex;
    
    /** 回溯栈：记录可能需要回溯的位置 */
    private final Stack<Integer> backtrackStack;
    
    /**
     * 构造函数
     * 
     * @param nodes 拓扑节点列表
     */
    public TopologyIterator(List<TopoNode> nodes) {
        this.nodes = nodes != null ? nodes : new ArrayList<>();
        this.currentIndex = 0;
        this.backtrackStack = new Stack<>();
    }
    
    /**
     * 判断是否还有下一个节点
     * 
     * @return true表示还有未遍历的节点
     */
    @Override
    public boolean hasNext() {
        return currentIndex < nodes.size();
    }
    
    /**
     * 获取下一个节点
     * 
     * @return 当前节点
     * @throws NoSuchElementException 如果没有更多节点
     */
    @Override
    public TopoNode next() {
        if (!hasNext()) {
            throw new NoSuchElementException("没有更多节点可遍历");
        }
        return nodes.get(currentIndex++);
    }
    
    /**
     * 获取当前索引位置（下一个要访问的节点索引）
     * 
     * @return 当前索引
     */
    public int getCurrentIndex() {
        return currentIndex;
    }
    
    /**
     * 标记回溯点
     * <p>在可能需要回溯的位置（如联调触发点）调用此方法
     */
    public void markBacktrackPoint() {
        backtrackStack.push(currentIndex);
    }
    
    /**
     * 回溯到最近的标记点
     * <p>联调完成后，回到联调起点，继续处理后续节点
     */
    public void backtrack() {
        if (!backtrackStack.isEmpty()) {
            currentIndex = backtrackStack.pop();
        }
    }
    
    /**
     * 回溯到指定位置
     * 
     * @param index 目标索引位置
     */
    public void backtrackTo(int index) {
        if (index >= 0 && index < nodes.size()) {
            currentIndex = index;
        }
    }
    
    /**
     * 跳到指定位置
     * <p>用于联调完成后跳过已处理的节点
     * 
     * @param index 目标索引位置
     */
    public void jumpTo(int index) {
        if (index >= 0 && index <= nodes.size()) {
            currentIndex = index;
        }
    }
    
    /**
     * 获取总节点数
     * 
     * @return 节点总数
     */
    public int size() {
        return nodes.size();
    }
    
    /**
     * 重置迭代器到起始位置
     */
    public void reset() {
        currentIndex = 0;
        backtrackStack.clear();
    }
    
    /**
     * 获取指定索引的节点（不改变当前位置）
     * 
     * @param index 节点索引
     * @return 指定位置的节点
     * @throws IndexOutOfBoundsException 如果索引越界
     */
    public TopoNode get(int index) {
        return nodes.get(index);
    }
}

